package jp.sourceforge.akjrcp.text_douga.audio;

import java.io.IOException;
import java.io.OutputStream;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import jp.sourceforge.akjrcp.text_douga.AudioData;
import jp.sourceforge.akjrcp.text_douga.AudioSystem;
import jp.sourceforge.akjrcp.text_douga.DougaPreference;
import jp.sourceforge.akjrcp.text_douga.DougaSystem;


public class FileAudioData implements AudioData{
	public static Log log=LogFactory.getLog(FileAudioData.class);
	
	/*
	 * synch usually used by same video for set exactlly time
	 */
private double synchLength;
private int loop;
private double startTime;
private double duration;
private double loopPadTime;//loop only
private String inputPath;
private boolean canStopInLoop=true;//exactlly time base
private double logicalTime;	//usually set by ffmpeg file info
public FileAudioData(String inputPath){
	this.inputPath=inputPath;
}

private boolean synch;
public double getDuration() {
	return duration;
}
public void setDuration(double duration) {
	this.duration = duration;
}
public String getInputPath() {
	return inputPath;
}
public void setInputPath(String inputPath) {
	this.inputPath = inputPath;
}
public double getSyncLength() {
	return synchLength;
}
public void setSynchLength(double logicalLength) {
	this.synchLength = logicalLength;
}
public int getLoop() {
	return loop;
}
public void setLoop(int loop) {
	this.loop = loop;
}
public double getLoopPadTime() {
	return loopPadTime;
}
public void setLoopPadTime(double loopPadTime) {
	this.loopPadTime = loopPadTime;
}
public double getStartTime() {
	return startTime;
}
public void setStartTime(double startTime) {
	this.startTime = startTime;
}
public boolean isSyncLength() {
	return synch;
}
public void setSynch(boolean fitLogicalLength) {
	this.synch = fitLogicalLength;
}
public boolean isCanStopInLoop() {
	return canStopInLoop;
}
public void setCanStopInLoop(boolean canStopInLoop) {
	this.canStopInLoop = canStopInLoop;
}



private double getWriteDuration(){
	double dr=AudioInput.NOT_SPECIFIED;
	if(this.getDuration()<=0){//0 or not specified
	
		dr=getLogicalTime()-startTime;
		
	if(this.isSyncLength()){
		dr=this.getSyncLength();
		}
	
	if(dr<=0){
		log.warn("duration is  0: maybe video is 0");
		//do nothing.
		return 0;
	}
	
	}else{
	dr=this.getDuration();
	}
	return dr;
}
public long writeData(DougaPreference preference,OutputStream outputStream,long maxbytes) throws IOException{
	long writed=0;
	if(this.getLoop()>0 || this.getLoop()==AudioSystem.FOREEVER){
	//for LOOP forever.
	if(maxbytes<=0 && this.getLoop()==AudioSystem.FOREEVER){
		log.warn("never stop:"+this);
		return 0;
		}
	double dr=getWriteDuration();
	log.info("inloop:writed=:"+dr+"duration="+duration+" sync="+this.getSyncLength()+" logical="+this.getLogicalTime());
	
	writed=AudioUtils.loopAudio(preference.getFfmpegPath(), this.getInputPath(), this.getStartTime(), dr, this.getLoop(),this.getLoopPadTime(),this.isCanStopInLoop(),maxbytes,outputStream);
	}else{
		double dr=getWriteDuration();
		log.info("incopy:dr="+dr+"duration="+duration+" sync="+this.getSyncLength()+" logical="+this.getLogicalTime());
		
		writed=AudioUtils.copyAudio(preference.getFfmpegPath(), this.getInputPath(), this.getStartTime(), dr, outputStream);
		
	}
	return writed;
}


public double getTotalTime() {
	if(loop==DougaSystem.FOREEVER){
		return DougaSystem.FOREEVER;
	}
	int lo=1;
	if(loop>1){
		lo=loop;
	}
	double d=duration;
	if(d==0){
		d=logicalTime;
	}
	//BUG if it's synch audio wrong.
	return d*lo+(lo-1)*loopPadTime;
}

public double getLogicalTime() {
	return logicalTime;
}
public void setLogicalTime(double logitalLength) {
	this.logicalTime = logitalLength;
}

public String toString(){
	return "start="+startTime+" duration="+duration+" loop="+loop+" canStopInLoop="+canStopInLoop+" inputPath="+inputPath+" synctime="+synchLength+" logicaltime="+logicalTime;	
	}

}
